package com.wwcom.darteagle.model;

import java.util.ArrayList;
import java.util.List;

public class MatchLegs extends Match {
	protected List<Leg> legs;

	protected Leg currentLeg;
	private MatchPlayer legWinner;
	private boolean isLegComplete;
	private boolean isMatchComplete;

	
	public MatchLegs() {
		super();
	}

	public MatchLegs(MatchInfo matchInfo) {
		super(matchInfo);
	}
	
	
	@Override
	protected void initialiseSelf() {
		super.initialiseSelf();
		legs= null;
		currentLeg= null;
		legWinner= null;
		isLegComplete= false;
		isMatchComplete= false;
	}
	

	//accessors
	@Override
	public int getNumSets() {
		return 0;
	}
	
	@Override
	public void setNumSets(int numSets) {
		if (numSets > 0)
			throw new RuntimeException("Sets not supported in MatchLegs");
	}	
	
	@Override
	public MatchPlayer getLegWinner() {
		return legWinner;
	}
	
	@Override
	public List<Leg> getLegs() {
		return legs;		
	}
	
	
	@Override
	public MatchPlayer getSetWinner() {
		throw new RuntimeException("MatchLegs::getSetWinner - unimplemented in MatchLegs");		
	}
	
	@Override
	public boolean isLegComplete() {
		return isLegComplete;
	}

	@Override
	public boolean isSetComplete() {
		return false;
	}

	@Override
	public boolean isMatchComplete() {
		return isMatchComplete;
	}
	
	@Override
	public int getLegNumber() {
		return legs.size()-1;
	}
	
	@Override
	public int getSetNumber() {
		return -1;  //no sets in a legs match
	}	
	
	//display and messages
	@Override
	public List< List<VisitScore> > getLegHistory() {
		return currentLeg.getLegHistory();
	}

	protected void updateLegHistory() {
	   currentLeg.updateLegHistory(matchPlayers);
	}
	
	@Override
	public List<VisitScore> getPlayerCurrentScores() {
		return currentLeg.getPlayerCurrentScores();
	}
	
	protected void updatePlayerCurrentScores() {
		currentLeg.updatePlayerCurrentScores(matchPlayers);
	}
	
	//playing logic
	@Override
	public void startPlaying() {
		super.startPlaying(); //super class handles player logic
		if (legs != null)
			throw new RuntimeException("MatchLegs::startPlaying - legs not null");
		//create legs list
		legs= new ArrayList<Leg>();
		//add new leg
		addLeg();
		//update scores
		updatePlayerCurrentScores();
	}
	
	@Override
	public void startPlaying(MatchPlayer matchPlayer) {
		super.startPlaying(matchPlayer); //super class handles player logic
		if (legs != null)
			throw new RuntimeException("MatchLegs::startPlaying - legs not null");
		//create legs list
		legs= new ArrayList<Leg>();
		//add new leg
		addLeg();
		//update scores
		updatePlayerCurrentScores();
	}	
	
	@Override
	public void nextPlayer() {
		//add player statistics first before we finalise which puts an empty score on the list
		addPlayerStatistics(currentPlayer, getCurrentPlayerScore());

		//finalise
		currentLeg.finalisePlayerVisitScore(currentPlayer);
		
		//update display lists
		updateLegHistory();
		updatePlayerCurrentScores();


		//check for leg winner
		if (currentLeg.isLegWon()) {
			isLegComplete= true;
			legWinner= currentLeg.getLegWinner();

			//update matchPlayers
			legWinner.incNumLegs();
			
			if (legWinner.getNumLegs() >= matchInfo.getNumLegs()) {
				isMatchComplete= true;
			}
			
		}
		super.nextPlayer();		
	}
	
	@Override
	public void nextLeg() {
		super.nextLeg(); //handles player rotation
		addLeg();
		updateLegHistory();
		updatePlayerCurrentScores();
		isLegComplete= false;
		legWinner= null;
	}
	
	private void addLeg() {
		Leg leg= new Leg(matchInfo,matchPlayers,getLegStartPlayer(),legs.size());
		legs.add(leg);
		//set current leg
		currentLeg= legs.get(legs.size()-1);
	}
	
	//scoring
	@Override
	public VisitScore updateCurrentPlayerScore( Score score ) {
		currentLeg.updatePlayerVisitScore(currentPlayer, score);
		return currentLeg.getPlayerVisitScore(currentPlayer);
	}	
	
	@Override
	public VisitScore updatePlayerScore(MatchPlayer matchPlayer, int visitInd, Score score ) {
		currentLeg.updatePlayerVisitScore(matchPlayer, visitInd, score);	
		return currentLeg.getPlayerVisitScore(matchPlayer, visitInd);
	}
	
	@Override
	public void finalisePlayerScore(MatchPlayer matchPlayer, int visitInd) {
		currentLeg.finalisePlayerVisitScore(matchPlayer, visitInd);		
		//check for leg winner
		if (currentLeg.isLegWon()) {
			isLegComplete= true;
			legWinner= currentLeg.getLegWinner();

			//update matchPlayers
			legWinner.incNumLegs();
			
			if (legWinner.getNumLegs() >= matchInfo.getNumLegs()) {
				isMatchComplete= true;
			}			
		}
		
		//update statistics
		updatePlayerStatistics(matchPlayer);

	}
		
	@Override
	public void unFinalisePlayerScore(MatchPlayer matchPlayer, int visitInd) {
		currentLeg.unFinalisePlayerVisitScore(matchPlayer, visitInd);	
	}	
	
	@Override
	public VisitScore getCurrentPlayerScore() {
		return currentLeg.getPlayerVisitScore(currentPlayer);
	}	
	

	@Override
	public VisitScore getVisitScore(MatchPlayer matchPlayer, int visitInd) {
		return currentLeg.getPlayerVisitScore(matchPlayer,visitInd);
	}
	
	//statistics
	@Override	
	public List<DartStats> getPlayerStatsLeg(int setInd, int legInd) {
		if (setInd != -1)
			throw new RuntimeException("MatchLeg::getPlayerStatsLeg - setInd not -1");
		return legs.get(legInd).getPlayerStats();
	}
	
	@Override	
	public List<DartStats> getPlayerStatsSet(int setInd) {
		throw new RuntimeException("MatchLeg::getPlayerStatsCurrentSet - unimplemented in MatchLeg");
	}
	
	@Override	
	protected List<VisitScore> getPlayerMatchHistory(MatchPlayer matchPlayer) {
		List < VisitScore > pmh= new ArrayList<VisitScore>();		
		for (Leg l : legs) {
			for (List <VisitScore> lvs : l.getLegHistory()) {
				for (VisitScore vs : lvs) {
					if (vs != null && vs.getMatchPlayer().equals(matchPlayer)) {
						pmh.add(vs);
					}
				}
			}
		}
		return pmh;
	}	
			
	//database serialisation
	public List<VisitScore> getAllVisitScoresInVisitOrder() {		
		List<VisitScore> vsList= new ArrayList<VisitScore>();
		for (Leg l : legs) {
			vsList.addAll(l.getAllVisitScoresInVisitOrder());
		}
		return vsList;
	}
		
}
